package com.Hermes.User;

import it.unisa.dia.gas.jpbc.Element;

import javax.crypto.IllegalBlockSizeException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

public class Arr {
    private final PRF_PRP_Hash pph;
    private final int mainid;
    private final Floyd_Warshall fw;

    private final node n1;
    private final PD_oracle pdo;
    private final ArrayList<node> apl;
    private final Element[][] Encnode;//0:x,1:y
    private final Element[][] Encesd;
    private final ConcurrentHashMap<Long, Long> ii2i;
    public ConcurrentHashMap<Integer, Arrnode> data;

    public Arr(node _n1, PRF_PRP_Hash _pph, Floyd_Warshall _fw, PD_oracle _pdo, ArrayList<node> _apl, PreEnc _preEnc, ConcurrentHashMap<Long, Long> ii2i) {//创建first
        pph = _pph;
        n1 = _n1;
        mainid = _n1.index;
        fw = _fw;
        pdo = _pdo;
        this.ii2i = ii2i;
        data = new ConcurrentHashMap<>();
        apl = _apl;
        Encnode = _preEnc.getEncnode();
        Encesd = _preEnc.getEncesd();

        byte[] tmpkr = ByteTools.merge(n1.kv.toByteArray(), n1.rv.toByteArray());


        byte[] res = new byte[32];
        pph.use_H2(tmpkr, res);//SHA256,|out|=256bits

        Element[] elements = Encnode[n1.index];
        Element ex = elements[0];
        Element ey = elements[1];
        byte[] bexy = ByteTools.merge(ex.duplicate().toBytes(), ey.duplicate().toBytes());
        byte[] firstB = ByteTools.XOR(bexy, res);
        Arrnode tmp = new Arrnode(firstB, n1.rv);
        data.put(0, tmp);

    }


    private String pdo2str(PD_Oracle_node pdonode) {
        var al = pdonode.pd_pointlist;
        var tmp = new BigDecimal(pdonode.pd_pointlist.get(0)).toBigInteger().toByteArray();

        for (int i = 1; i < al.size() - 1; i++) {
            tmp = ByteTools.merge(tmp, new BigDecimal(pdonode.pd_pointlist.get(i)).toBigInteger().toByteArray());
        }
        tmp = ByteTools.merge(tmp, new BigDecimal(pdonode.pd_pointlist.get(al.size() - 1)).toBigInteger().toByteArray());
        return new BigInteger(tmp).toString();
    }

    public void buildArr() throws IllegalBlockSizeException {
        for (int i = 0; i < apl.size(); i++) {
            int id2 = apl.get(i).index;
            if (mainid == id2) continue;
            var g = fw.getGraph();
            Element esd = Encesd[mainid][id2];

            byte[] besd = esd.duplicate().toBytes();
            byte[] vidS = new BigDecimal(ii2i.get(apl.get(i).id)).toBigInteger().toByteArray();
            byte[] tagh1;
            tagh1 = pph.use_H1(vidS);

            byte[] tagt1 = new byte[vidS.length];
            pph.use_T1(vidS, tagt1);


            var pd_oracle_node = pdo.find(mainid, id2);

            String spvv = pdo2str(pd_oracle_node);
            BigInteger spvvB = new BigInteger(spvv);

            byte[] tagh2 = new byte[32];
            byte[] tmpkr = ByteTools.merge(n1.kv.toByteArray(), n1.rv.toByteArray());
            pph.use_H2(tmpkr, tagh2);
            byte[] msgh1_rv = apl.get(i).rv.toByteArray(), tagh1_rv, tagf3h1 = new byte[32];
            tagh1_rv = pph.use_H1(msgh1_rv);
            pph.use_F3(tagh1_rv, tagf3h1);

            byte[] s2 = ByteTools.XOR(spvvB.toByteArray(), tagf3h1);
            byte[] tmpb1 = ByteTools.merge3(tagh1, besd, s2);
            byte[] res = ByteTools.XOR(tmpb1, tagh2);
            Arrnode arrnode = new Arrnode(res, apl.get(i).rv);
            data.put(new BigInteger(tagt1).intValue(), arrnode);
        }
    }

}